<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="author" content="Olivia McCallum">
    <meta name="description" content="A p5.js displaying a simple particle system with wind.">

    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Reddit+Mono:wght@200..900&display=swap" rel="stylesheet">

    <title>Particle System Sketch</title>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.min.js" integrity="sha512-d6sc8kbZEtA2LwB9m/ck0FhvyUwVfdmvTeyJRprmj7Wg9wRFtHDIpr6qk4g/y3Ix3O9I6KHIv6SGu9f7RaP1Gw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <style>
    #instructions {
        position: absolute;
        top: 10px;
        left: 10px;
        font-family: "Reddit Mono", monospace;
        font-size: 16px;
        color: rgb(0, 60, 150);
        background-color: rgba(255, 255, 255, 0.8);
        padding: 10px;
        border-radius: 5px;
    }
    </style>
    <script>
    let gravity, wind;
    let systems = [];

    function setup() {
        createCanvas(windowWidth, windowHeight);

        gravity = createVector(0, 0.05);  
        wind = createVector(2, 0);

        systems = [];
    }

    function draw() {
        background(255);

        for (let ps of systems) {
            ps.addForce(gravity);
            ps.update();
            ps.display();
        }
    }

    function mousePressed() {
        systems.push(new System(mouseX, mouseY, 60));
    }

    function keyPressed() {
        if (key === 'r') {
            setup();
        }
        if (key === 'w') {
            for (let ps of systems) {
            ps.addForce(wind);
            }
        }
    }

    class System {
    constructor(x, y, c) {
        this.origin = createVector(x, y);
        this.particles = [];
        this.count = c;
    }

    addForce(f) {
        for (let i = 0; i < this.particles.length; i++) {
        this.particles[i].addForce(f);
        }
    }

    update() {
        if (this.count > 0) {
        // update the system
        this.particles.push(new Particle(this.origin.x, this.origin.y));
        this.count--;
        }

        // remove dead particles
        for (let i = this.particles.length - 1; i >= 0; i--) {
        if (this.particles[i].expired()) {
            this.particles.splice(i, 1);
        }
        }

        // for every particle
        for (let i = 0; i < this.particles.length; i++) {
        let p = this.particles[i];
        p.update();
        }
    }

    display() {
        // draw the system
        for (let i = 0; i < this.particles.length; i++) {
        let p = this.particles[i];
        p.display();
        }
    }
    }

    class Particle {
    constructor(x, y) {
        this.position = createVector(x, y);
        this.velocity = createVector(random(-1, 1), random(-1, 1));
        this.acceleration = createVector(0, 0);
        this.lifespan = 255;
        this.decay = 2;
    }

    addForce(f) {
        this.acceleration.add(f);
    }

    expired() {
        return this.lifespan < 0;
    }

    update() {
        this.lifespan -= this.decay;

        this.velocity.add(this.acceleration);
        this.position.add(this.velocity);

        if (this.position.y > height) {
        this.position.y = height;
        this.velocity.y *= -0.5;
        }

        this.acceleration.mult(0);
    }

    display() {
        push();
        translate(this.position.x, this.position.y);
        noStroke();
        fill(0, 60, 150, this.lifespan);
        ellipse(0, 0, 10);
        pop();
    }
    }

    </script>
</head>
<body>
    <div id="instructions">
        Click to create particles. Press 'w' to apply wind. Press 'r' to reset.
      </div>
</body>
</html>
